// ========== Copyright Header Begin ==========================================
// 
// OpenSPARC T1 Processor File: Ni_Trap.cc
// Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// 
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// 
// The above named program is distributed in the hope that it will be 
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// 
// ========== Copyright Header End ============================================
/************************************************************************
**  
**  Copyright (C) 2002, Sun Microsystems, Inc.
**
**  Sun considers its source code as an unpublished, proprietary
**  trade secret and it is available only under strict license provisions.
**  This copyright notice is placed here only to protect Sun in the event 
**  the source is deemed a published work. Disassembly, decompilation,
**  or other means of reducing the object code to human readable form
**  is prohibited by the license agreement under which this code is
**  provided to the user or company in possession of this copy."
**
*************************************************************************/
#include "Ni/Ni_Trap.h"
#include "StdMacros.h"
#include <sstream>

using namespace std;
using namespace Riesling;

Ni_Trap::Ni_Trap()
{}

Ni_Trap::Ni_Trap( uint_t trapType ) :
    BasicTrap( trapType )
{}

Ni_Trap::Ni_Trap( const Ni_Trap & orig ) :
    BasicTrap( orig )
{}

Ni_Trap::~Ni_Trap()
{}

const Ni_Trap &
Ni_Trap::operator=( const Ni_Trap & rhs )
{
    BasicTrap::operator=( rhs );

    return *this;
}

bool
Ni_Trap::operator==( const Ni_Trap & rhs ) const
{ 
    return BasicTrap::operator==( rhs );
}

string
Ni_Trap::toString() const
{
    ostringstream os;

    switch( trapType_ ) {
    case power_on_reset:
	os << "power_on_reset";
	break;
    case watchdog_reset:
	os << "watchdog_reset";
	break;
    case externally_initiated_reset:
	os << "externally_initiated_reset";
	break;
    case software_initiated_reset:
	os << "software_initiated_reset";
	break;
    case RED_sate_exeption:
	os << "RED_sate_exeption";
	break;
    case instruction_access_exception:
	os << "instruction_access_exception";
	break;
    case instruction_access_MMU_miss:
	os << "instruction_access_MMU_miss";
	break;
    case instruction_access_error:
	os << "instruction_access_error";
	break;
    case illegal_instruction:
	os << "illegal_instruction";
	break;
    case privileged_opcode:
	os << "privileged_opcode";
	break;
    case unimplemented_LDD:
	os << "unimplemented_LDD";
	break;
    case unimplemented_STD:
	os << "unimplemented_STD";
	break;
    case fp_disabled:
	os << "fp_disabled";
	break;
    case fp_exception_ieee_754:
	os << "fp_exception_ieee_754";
	break;
    case fp_exception_other:
	os << "fp_exception_other";
	break;
    case tag_overflow:
	os << "tag_overflow";
	break;
    case clean_window:
	os << "clean_window";
	break;
    case division_by_zero:
	os << "division_by_zero";
	break;
    case internal_processor_error:
	os << "internal_processor_error";
	break;
    case data_access_exception:
	os << "data_access_exception";
	break;
    case data_access_MMU_miss:
	os << "data_access_MMU_miss";
	break;
    case data_access_error:
	os << "data_access_error";
	break;
    case data_access_protection:
	os << "data_access_protection";
	break;
    case mem_address_not_aligned:
	os << "mem_address_not_aligned";
	break;
    case LDDF_mem_address_not_aligned:
	os << "LDDF_mem_address_not_aligned";
	break;
    case STDF_mem_address_not_aligned:
	os << "STDF_mem_address_not_aligned";
	break;
    case privileged_action:
	os << "privileged_action";
	break;
    case LDQF_mem_address_not_aligned:
	os << "LDQF_mem_address_not_aligned";
	break;
    case STQF_mem_address_not_aligned:
	os << "STQF_mem_address_not_aligned";
	break;
    case inst_real_translation_miss:
	os << "inst_real_translation_miss";
	break;
    case data_real_translation_miss:
	os << "data_real_translation_miss";
	break;
    case async_data_error:
	os << "async_data_error";
	break;
    case interrupt_level_1:
	os << "interrupt_level_1";
	break;
    case hstick_match:
	os << "hstick_match";
	break;
    case trap_level_zero:
	os << "trap_level_zero";
	break;
    case interrupt_vector_trap:
	os << "interrupt_vector_trap";
	break;
    case PA_watchpoint:
	os << "PA_watchpoint";
	break;
    case VA_watchpoint:
	os << "VA_watchpoint";
	break;
    case ECC_error:
	os << "ECC_error";
	break;
    case fast_instruction_access_MMU_miss:
	os << "fast_instruction_access_MMU_miss";
	break;
    case fast_data_access_MMU_miss:
	os << "fast_data_access_MMU_miss";
	break;
    case fast_data_access_protection:
	os << "fast_data_access_protection";
	break;
    case control_transfer_instruction:
	os << "control_transfer_instruction";
	break;
    case instruction_breakpoint:
	os << "instruction_breakpoint";
	break;
    case hw_changed:
	os << "hw_changed";
	break;
    case cpu_mondo_trap:
	os << "cpu_mondo_trap";
	break;
    case dev_mondo_trap:
	os << "dev_mondo_trap";
	break;
    case resumable_error:
	os << "resumable_error";
	break;
    case nonresumable_error:
	os << "nonresumable_error";
	break;
    case spill_0_normal:
	os << "spill_0_normal";
	break;
    case spill_0_other:
	os << "spill_0_other";
	break;
    case fill_0_normal:
	os << "fill_0_normal";
	break;
    case fill_0_other:
	os << "fill_0_other";
	break;
    default:
	os << "** UNKNOWN TRAP TYPE " << trapType_ << " **";
	break;
    }

    return os.str();
}

uint_t
Ni_Trap::getTrapPriority() const
{

    if( trapType_ >= 0x041 && trapType_ <= 0x04f ){
	return  32 - ( trapType_ & 0x00f );
    }

    uint_t priority;

    switch( trapType_ ){
    case power_on_reset:
	priority = 0;
	break;

    case watchdog_reset:
    case externally_initiated_reset:
    case software_initiated_reset:
    case RED_sate_exeption:
	priority = 1;
	break;

    case instruction_access_MMU_miss:
    case async_data_error:
    case fast_instruction_access_MMU_miss:
	priority = 2;
	break;

    case instruction_access_error:
	priority = 3;
	break;

    case internal_processor_error:
	priority = 4;
	break;

    case instruction_access_exception:
	priority = 5;
	break;

    case privileged_opcode:
    case unimplemented_LDD:
    case unimplemented_STD:
	priority = 6;
	break;

    case illegal_instruction:
	priority = 7;
	break;

    case fp_disabled:
	priority = 8;
	break;

    case spill_0_normal:
    case spill_0_other:
    case fill_0_normal:
    case fill_0_other:
	priority = 9;
	break;

    case clean_window:
    case mem_address_not_aligned:
    case LDDF_mem_address_not_aligned:
    case STDF_mem_address_not_aligned:
    case LDQF_mem_address_not_aligned:
    case STQF_mem_address_not_aligned:
	priority = 10;
	break;

    case fp_exception_ieee_754:
    case fp_exception_other:
    case privileged_action:
    case VA_watchpoint:
	priority = 11;
	break;

    case data_access_exception:
    case data_access_MMU_miss:
    case data_access_error:
    case data_access_protection:
    case PA_watchpoint:
    case fast_data_access_MMU_miss:
	priority = 12;
	break;

    case tag_overflow:
	priority = 14;
	break;

    case division_by_zero:
	priority = 15;
	break;

    case interrupt_vector_trap:
	priority = 16;
	break;

    case ECC_error:
	priority = 33;
	break;

    case inst_real_translation_miss:
    case data_real_translation_miss:
//     case real_address_mmu_miss:
    case interrupt_level_1:
    case hstick_match:
    case trap_level_zero:
    case fast_data_access_protection:
    case control_transfer_instruction:
    case instruction_breakpoint:
    case hw_changed:
    case cpu_mondo_trap:
    case dev_mondo_trap:
    case resumable_error:
    case nonresumable_error:
	RIESLING_THROW_DOMAIN_ERROR( "Unknown trap priority" );
	break;

    default:
	RIESLING_THROW_DOMAIN_ERROR( "Unknown trap type" );
	break;
    }

    return priority;
}

void 
Ni_Trap::snapshot( SS_SnapShot &ss, const char *prefix )
{
    BasicTrap::snapshot(ss, prefix);

    // Any local variables should be snapshot-ed here.
}
